package com.example.commons.future;

import com.example.commons.model.BizResMsg;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class SyncMsgFuture<RES> implements MsgFuture<RES> {

    private final CountDownLatch latch = new CountDownLatch(1);
    private final long begin = System.currentTimeMillis();
    private long timeout;
    private BizResMsg<RES> response;
    private final String reqId;
    private boolean writeResult;
    private Throwable cause;
    private boolean isTimeout = false;

    public SyncMsgFuture(String reqId) {
        this.reqId = reqId;
    }

    public SyncMsgFuture(String reqId, long timeout) {
        this.reqId = reqId;
        this.timeout = timeout;
        writeResult = true;
        isTimeout = false;
    }

    @Override
    public Throwable cause() {
        return cause;
    }

    @Override
    public void setCause(Throwable cause) {
        this.cause = cause;
    }

    @Override
    public boolean isWriteSuccess() {
        return writeResult;
    }

    @Override
    public void setWriteResult(boolean result) {
        this.writeResult = result;
    }

    @Override
    public String setReqId() {
        return reqId;
    }

    @Override
    public BizResMsg<RES> response() {
        return response;
    }

    @Override
    public void setRes(BizResMsg<RES> response) {
        this.response = response;
        latch.countDown();
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return true;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    @Override
    public boolean isDone() {
        return false;
    }

    @Override
    public BizResMsg<RES> get() throws InterruptedException {
        latch.wait();
        return response;
    }

    @Override
    public BizResMsg<RES> get(long timeout, TimeUnit unit) throws InterruptedException {
        if (latch.await(timeout, unit)) {
            return response;
        }
        return null;
    }

    @Override
    public boolean isTimeout() {
        if (isTimeout) {
            return isTimeout;
        }
        return System.currentTimeMillis() - begin > timeout;
    }

    @Override
    public long getBegin() {
        return begin;
    }
}